﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace Perceiveit.Xml
{
    /// <summary>
    /// The XFactory is an abstract class that supports the mapping between XNames and XEntity's.
    /// It can create qualified names for specific instances
    /// and conversely class instances for qualified names.
    /// </summary>
    /// <typeparam name="T">The actual or common type this factory will create instances of
    /// and provide names for.</typeparam>
    public abstract class XFactory<T> where T : XEntity
    {
        //
        // public methods
        //

        /// <summary>
        /// Returns true if the XName is a known name for this factory
        /// </summary>
        /// <param name="name">The name to check</param>
        /// <param name="factory">Set to the specific factory which knows the name, or null</param>
        /// <returns>True if this factory knows the name</returns>
        public abstract bool IsKnownName(XName name, out XFactory<T> factory);

        /// <summary>
        /// Checks the entities type and returns true is this factory knows about the type
        /// </summary>
        /// <param name="entity">The entity to check</param>
        /// <param name="factory">Set to the specific factory which knows this entity</param>
        /// <returns>True if the entity is a known entity for this factory</returns>
        public abstract bool IsKnownEntity(T entity, out XFactory<T> factory);

        /// <summary>
        /// Returns a new un-initialized XEntity instance of type T for the specified XName
        /// </summary>
        /// <param name="name">The name that corresponds to the type of the XEntity</param>
        /// <returns>A new un-initialized XEntity</returns>
        public abstract T GetEntityForName(XName name);

        /// <summary>
        /// Returns the XName for an XEntity this factory has previously declared as known to itself
        /// </summary>
        /// <param name="entity">The XEntity to create the name for</param>
        /// <returns>The XName of the entity</returns>
        public abstract XName GetNameForEntity(T entity);



        protected bool IsMatchingName(XName factoryName, XName elementName)
        {
            if (string.IsNullOrEmpty(factoryName.NamespaceName))
                return factoryName.LocalName == elementName.LocalName;
            else
                return factoryName == elementName; 
        }
    }

    
}
